package com.lf.filter;

import com.lf.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpCookie;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.time.ZonedDateTime;
import java.util.*;


// 定义全局过滤器，会对所有路由生效
@Slf4j
@Component
public class TokenFilter implements GlobalFilter, Ordered {

    @Reference
    private UserService userService;

    // ip 防暴刷相关参数获取
    @Value("${register-user.minutes}")
    private Integer minutes;
    @Value("${register-user.times}")
    private Integer times;

    private Map<String, LinkedList<ZonedDateTime>> registerMap = new HashMap<>();

    private List<String> noTokenUrl = new ArrayList<String>(){
        {
            add("/api/user/register/"); // 注册接口不需要验证 token
            add("/api/user/isRegistered/"); // 判断是否已注册，也不需要验证token
            add("/api/user/login/"); // 登录接口不需要验证 token
            add("/api/code/create/"); // 申请生成验证码发送不需要验证 token
        }
    };

    public boolean checkIfNeedToken(String path) {
        boolean result = true;
        for (String s : noTokenUrl) {
            if(path.startsWith(s)) {
                result = false;
                break;
            }
        }
        return result;
    }


    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 获取到相关的 request 和 response 结构
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();

        MultiValueMap<String, HttpCookie> cookies = request.getCookies();
        String token = "";
        if(cookies.get("token") != null && cookies.get("token").size() > 0) {
            token = cookies.get("token").get(0).getValue();
        }


        // 判断是否需要进行 token 检查
        if(checkIfNeedToken(request.getPath().toString())){
            if("".equals(token)) { // 没有在请求中找到 token
                response.setStatusCode(HttpStatus.UNAUTHORIZED);
                String errorMsg = " - - - request cookie have no token - - - ";
                DataBuffer wrap = response.bufferFactory().wrap(errorMsg.getBytes());
                return response.writeWith(Mono.just(wrap));
            } else {
                String email = userService.getEmailByToken(token);
                System.out.println("token : " + token + "email: " + email);
                if(email == null || "".equals(email)) {
                    response.setStatusCode(HttpStatus.UNAUTHORIZED);
                    String errorMsg = " - - - invalid token - - - ";
                    DataBuffer wrap = response.bufferFactory().wrap(errorMsg.getBytes());
                    return response.writeWith(Mono.just(wrap));
                }
            }
        }


//        if(request.getPath().toString().contains("register")) { // 若请求为注册接口，进行 IP防暴刷 监测
//            // 获取到客户端 ip
//            String ip = request.getRemoteAddress().getHostString();
//            // 获取到该ip 对register 接口的请求记录
//            LinkedList<ZonedDateTime> list = registerMap.get(ip);
//            if(list != null) {
//                // 根据 X 分钟即 minutes 参数创建时间节点
//                ZonedDateTime timeFlag = ZonedDateTime.now().minusMinutes(minutes);
//                // 遍历 list，将记录在 timeFlag 之后的进行计数
//                int count = 0;
//                ListIterator<ZonedDateTime> iterator = list.listIterator(list.size());
//                while(iterator.hasPrevious()) {
//                    if(iterator.previous().isAfter(timeFlag)) {
//                        count++;
//                    } else { // ip 请求是按顺序放入的，一旦发现不满足，就不需要再遍历更前面的请求记录了
//                        break;
//                    }
//                }
//                if(count > times) { // 请求已经超过预设的次数
//                    response.setStatusCode(HttpStatus.SEE_OTHER);
//                    String errorMsg = " - - - your register is too frequent,please try later - - - ";
//                    DataBuffer wrap = response.bufferFactory().wrap(errorMsg.getBytes());
//                    return response.writeWith(Mono.just(wrap));
//                }
//            }
//            registerMap.computeIfAbsent(ip, k -> new LinkedList<>());
//            registerMap.get(ip).add(ZonedDateTime.now());
//        }


        // 合法请求，放行，执行后续的过滤器
        return chain.filter(exchange);
    }

    // 返回值表示当前过滤器的顺序（优先级），数值越小，优先级越高
    @Override
    public int getOrder() {
        return 0;
    }
}
